package com.yy.yyui.scroll
{
	
	import com.yy.tools.graphics.GT;
	import com.yy.tools.graphics.Scale9GridDisplayObject;
	import com.yy.yyui.IActionList;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	public class ScrollPanel extends Sprite implements IActionList
	{
		private var _actions:Object;
		
		private var w:Number,h:Number;
		private var _scrollGap:Number;
		
		private var _contentScrollPanel:Sprite;//内容容器的父容器
		private var _contentPanel:Sprite;//内容容器
		private var _controlPanel:Sprite;//控制按钮容器 包括 向上按钮 向下按钮 和滑块
		private var _scrollBarPanel:Sprite;//装滑块的容器 父容器是_controlPanel
		private var _upButton:DisplayObject;//向上按钮
		private var _downButton:DisplayObject;//向下按钮
		private var _scrollBar:Sprite;//滚动坏块
		private var _scrollBarBackground:Sprite;
		private var _bg:DisplayObject;//背景
		private var _showBar:Boolean;
		
		public var moveState:Boolean = true;
		public var autoDispose:Boolean = true;
		
		public var batBackGround:DisplayObject;//滚动条背景
		private var dW:Number;
		private var dH:Number;
		private var auto:Boolean;
		
		/**
		 *滚动面板 
		 * @param width	滚动面板的宽
		 * @param height 滚动面板的高
		 * @param moveDis 滑块
		 * @param upDis	向上按钮
		 * @param downDis	向下按钮
		 * @param bg	背景
		 * @param showBar 内容未超过显示区域是否显示滚动条
		 * @param scrollGap 
		 * @param scrollGapV 
		 * @param auto
		 * @param autoDispose 移除舞台时是否释放自身资源
		 * 
		 */
		public function ScrollPanel(width:Number = 200, 	
									height:Number = 200,
									moveDis:DisplayObject = null,
									upDis:DisplayObject = null,
									downDis:DisplayObject = null,
									bg:DisplayObject = null,
									showBar:Boolean = false,
									scrollGap:Number = 5,
									scrollGapV:Number = 5,
									auto:Boolean = false,
									autoDispose:Boolean=true)
		{
			super();
			this.auto = auto;
			this._showBar = showBar;
			var dobj:DisplayObject;
			var btn:DisplayObject;
			var sp:Sprite;	
			if(bg == null)
			{
//				this._bg = GT.scale9(GT.createEmptyDisplayObject(1,1));
				this._bg = new Scale9GridDisplayObject(GT.createEmptyDisplayObject(1,1));
			}else
			{
				this._bg = bg;
			}
			this._bg.height = height;
			this._bg.x += width - this._bg.width;
			this.batBackGround = this.addChild(this._bg);
			
			this.w  = width;
			this.h =  height;
			this._scrollGap = scrollGap;
			
			//initialize panels
			sp = new Sprite();
			dobj = this.addChild(sp);
			this._contentScrollPanel = sp;
			
			sp = new Sprite();
			dobj = this.contentScrollPanel.addChild(sp);
			this._contentPanel = sp;
			
			
			sp = new Sprite();
			dobj = this.addChild(sp);
			dobj.visible = false;
			this._controlPanel = sp;
			
			//control parts
			//scroll buttons
			if(upDis != null)
			{
				btn = upDis;
			}else
			{
				btn = GT.createEmptyDisplayObject(1,1);
//				btn = GT.createScrollButton(GT.createEmptyDisplayObject(1,1));
			}
			dobj = this.controlPanel.addChild(btn);
			dobj.y = scrollGapV;
			dobj.x = (this.batBackGround.width - dobj.width)/2;
			this._upButton = btn;
			
			if(downDis != null)
			{
				btn = downDis;
			}else
			{
//				btn = GT.createScrollButton(GT.createEmptyDisplayObject(1,1));
				btn = GT.createEmptyDisplayObject(1,1);
			}
			dobj = this.controlPanel.addChild(btn);
			dobj.y = this.height - scrollGapV - dobj.height;
			dobj.x = (this.batBackGround.width - dobj.width)/2;
			this._downButton = btn;
			
			//scroll bar
			sp = new Sprite();
			dobj = this.controlPanel.addChild(sp);
			dobj.y = this.upButton.y + this.upButton.height;
			this._scrollBarPanel = sp;
			sp = new Scale9GridDisplayObject(GT.createEmptyDisplayObject(1,1));				
			sp.buttonMode = true;
			//			sp.visible = false;
			dobj = this.scrollBarPanel.addChild(sp);
			dobj.height = this.downButton.y - scrollBarPanel.y;
			dobj.width = batBackGround.width;
//			GT.enableMouseDownAlphaEffect(dobj);
			this._scrollBarBackground = sp;
			
			if(moveDis ==null)
			{
				sp = new Scale9GridDisplayObject(GT.createEmptyDisplayObject(1,1));		
			}else
			{
				if(this.auto)
				{
					this.dW = moveDis.width;
					this.dH = moveDis.height;
				}
				sp = new Scale9GridDisplayObject(moveDis);
			}
			sp.buttonMode = true;
			dobj = this.scrollBarPanel.addChild(sp);
			dobj.x = (this.batBackGround.width - dobj.width)/2;
			dobj.y = this.scrollBarBackground.y;
//			GT.enableMouseDownAlphaEffect(dobj);
			this._scrollBar = sp;
			
			//adjust panels
			expectedScrollBarY = 0;
			tweenScrollRectY = 0;
			this.controlPanel.x = this.width-this.controlPanel.width;
			this.contentScrollPanel.scrollRect = new Rectangle(0,0,this.width-this.controlPanel.width - this.scrollGap,this.height);
//			GT.fulFill3(this.contentScrollPanel,this.contentScrollPanel.scrollRect.width,this.height,0,0);
			
			updatePositions();
			
			//set actions
			this.oldBounds = this.contentPanel.getBounds(this.contentPanel);
			//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这里可以改进
			this.contentPanel.addEventListener(Event.ENTER_FRAME,contentPanelSizeChangedHandler);
			
			this.upButton.addEventListener(MouseEvent.CLICK,clickUpButtonHandler);		
			this.downButton.addEventListener(MouseEvent.CLICK,clickDownButtonHandler);
			this.scrollBar.addEventListener(MouseEvent.MOUSE_DOWN,startDragging);
			this.scrollBarBackground.addEventListener(MouseEvent.CLICK,clickScrollBarBackHandler);
			this.addEventListener(MouseEvent.MOUSE_WHEEL,onMouseWheelHandler);
			this._actions = {};
			
			
			this.autoDispose = autoDispose;
			if(autoDispose) {
				this.addEventListener(Event.REMOVED_FROM_STAGE,destroy);
			}
		}
		
		public function destroy(...rest):void{
			if(this.autoDispose) {
				this.removeEventListener(Event.REMOVED_FROM_STAGE,destroy);
				GT.destroyActions(this.actions);
				this.contentPanel.removeEventListener(Event.ENTER_FRAME,contentPanelSizeChangedHandler);
				this.upButton.removeEventListener(MouseEvent.CLICK,clickUpButtonHandler);		
				this.downButton.removeEventListener(MouseEvent.CLICK,clickDownButtonHandler);
				this.scrollBar.removeEventListener(MouseEvent.MOUSE_DOWN,startDragging);
				this.scrollBarBackground.removeEventListener(MouseEvent.CLICK,clickScrollBarBackHandler);
				this.removeEventListener(MouseEvent.MOUSE_WHEEL,onMouseWheelHandler);	
				GT.removeAllChild(this);				
			}
		}
		
		
		
		private var oldBounds:Rectangle;
		private function contentPanelSizeChangedHandler(e:Event):void{
			var rect:Rectangle = this.contentPanel.getBounds(this.contentPanel);
			if(rect.y!=oldBounds.y||rect.height!=oldBounds.height){
				oldBounds = rect;
				this.updatePositions();
				
			}
		}
		
		public function get actions():Object{return this._actions;}
		
		public function get contentScrollPanel():Sprite{return this._contentScrollPanel;}
		public function get contentPanel():Sprite{return this._contentPanel;}
		public function get controlPanel():Sprite{return this._controlPanel;}
		public function get scrollBarPanel():Sprite{return this._scrollBarPanel;}
		public function get upButton():DisplayObject{return this._upButton;}
		public function get downButton():DisplayObject{return this._downButton;}
		public function get scrollBar():Sprite{return this._scrollBar;}
		public function get scrollBarBackground():Sprite{return this._scrollBarBackground;}
		
		public function get scrollGap():Number{return this._scrollGap;}
		
		public function removeScrollBar():void{
			this.removeChild(this.controlPanel);
			this.contentScrollPanel.scrollRect = new Rectangle(0,0,this.width,this.height);
//			GT.fulFill3(this.contentScrollPanel,this.contentScrollPanel.scrollRect.width,this.height,0,0);
		}
		
		
		public var expectedScrollBarY:Number;
		public var tweenScrollRectY:Number;
		
		public function update(tween:Boolean = true):void{
			this.updatePositions(tween,false);
		}
		private function updatePositions(tween:Boolean = true,onClickBarBack:Boolean=false):void{
			var rect:Rectangle;
			if(this.auto)
			{
				this.scrollBar.visible = true;
				this._scrollBar.visible=this._bg.visible = this.controlPanel.visible = true;
				this.scrollBar.width = this.dW;
				this.scrollBar.height = this.dH;
				rect = this.contentScrollPanel.scrollRect;
				if(this.scrollBar.y <= 0)
				{
					this.scrollBar.y = 0;
					rect.y = 0;
				}
				if((this.scrollBar.y+this.scrollBar.height)>this.scrollBarBackground.height){
					this.scrollBar.y = this.scrollBarBackground.height - this.scrollBar.height;
				}
				var bl:Number = this.scrollBar.y / this.scrollBarBackground.height; 
				var contentRectc:Rectangle = this.contentPanel.getBounds(this.contentScrollPanel);
				if(contentRectc.height > this.contentScrollPanel.height)
				{
					if((this.scrollBar.y+this.scrollBar.height) == this.scrollBarBackground.height){
						rect.y = contentRectc.height -this.contentScrollPanel.height;
					}else
					{
						rect.y = bl*Number(contentRectc.height -this.contentScrollPanel.height);
					}
				}else
				{
					this.scrollBar.visible = false;
					this.scrollBar.y = 0;
					rect.y = 0;
				}
				this.contentScrollPanel.scrollRect = rect;
			}else
			{
				if(this.moveState)
				{
					var expectedHeight:Number = this.scrollBar.height;
					var contentRect:Rectangle = this.contentPanel.getBounds(this.contentScrollPanel);
					if(this.contentPanel.height==0||this.contentPanel.width == 0){
						this._bg.visible = this.controlPanel.visible = this._showBar;
						this._scrollBar.visible = false;
						return;
					}else{
						if(contentRect.height<=this.contentScrollPanel.scrollRect.height){
							this._bg.visible = this.controlPanel.visible = this._showBar;
							this._scrollBar.visible = false;
							expectedScrollBarY = 0;
							expectedHeight = this.scrollBarBackground.height;
						}else{
							expectedHeight = Math.round((this.scrollBarBackground.height*this.contentScrollPanel.scrollRect.height)/contentRect.height);
							this._scrollBar.visible=this._bg.visible = this.controlPanel.visible = true;
						}
					}
					//check expectedScrollBarY
					
					
					if(expectedScrollBarY<0){
						expectedScrollBarY = 0;
					}else if((expectedScrollBarY+expectedHeight)>this.scrollBarBackground.height){
						expectedScrollBarY = this.scrollBarBackground.height - expectedHeight;
					}
					if(!onClickBarBack){
						if(scrollBar.y<0){
							this.scrollBar.y = 0;
						}else if((scrollBar.y+this.scrollBar.height)>this.scrollBarBackground.height){
							scrollBar.y = this.scrollBarBackground.height - this.scrollBar.height;
						}			
					}
					//set scroll rect;
					//ratio
					rect = this.contentScrollPanel.scrollRect;
					if(this.controlPanel.visible){
						rect.y = (contentRect.height*expectedScrollBarY)/this.scrollBarBackground.height;//+contentRect.y;
					}else{
						rect.y = 0;
					}
					//				if(tween&&(this.scrollBar.y!=this.expectedScrollBarY||this.scrollBar.height!=expectedHeight)){
					//					TweenLite.to(this.scrollBar,0.5,{y:expectedScrollBarY,height:expectedHeight});
					//					//this.expectedScrollBarY = this.contentScrollPanel.scrollRect.y;
					//					TweenLite.to(this,0.5,{tweenScrollRectY:rect.y,onUpdate:tweenUpdate});
					//				}else{
					this.scrollBar.height = expectedHeight;
					this.contentScrollPanel.scrollRect = rect;
					this.scrollBar.y = expectedScrollBarY;
					
					//				}
				}
			}
		}
		
		private function tweenUpdate():void{
			var rect:Rectangle = this.contentScrollPanel.scrollRect;
			rect.y = this.tweenScrollRectY;
			this.contentScrollPanel.scrollRect = rect;
		}
		
		private function onMouseWheelHandler(e:MouseEvent):void{
			this.moveUp(e.delta*5);
			e.updateAfterEvent();
		}
		
		private function clickUpButtonHandler(e:MouseEvent):void{
			this.moveUp(this.scrollBarPanel.height/20);
			e.updateAfterEvent();
			//			TweenLite.removeTween(this.dragTween);
			//			expectedScrollBarY = this.scrollBar.y - (this.scrollBarPanel.height/20);
			//			update();
		} 
		
		private function clickDownButtonHandler(e:MouseEvent):void{
			this.moveDown(this.scrollBarPanel.height/20);
			e.updateAfterEvent();
			//			TweenLite.removeTween(this.dragTween);
			//			expectedScrollBarY = this.scrollBar.y+(this.scrollBarPanel.height/20);
			//			update();
		} 
		
		private function clickScrollBarBackHandler(e:MouseEvent):void{
			var ly:Number = e.localY;
			var rect:Rectangle = this.scrollBar.getBounds(this.scrollBarBackground);
			if(ly>rect.top){
				//				this.moveDown(this.scrollBar.height);
				expectedScrollBarY = this.scrollBar.y + this.scrollBar.height;
				updatePositions(true,true);
			}else if(ly<rect.bottom){
				//				this.moveUp(this.scrollBar.height);
				expectedScrollBarY = this.scrollBar.y - this.scrollBar.height;
				updatePositions(true,true);
			}
			e.updateAfterEvent();
		}
		
		private var oldY:Number;
		private var dragDiff:Number;
		private function startDragging(e:MouseEvent):void{
			oldY = e.stageY;
			dragDiff = 0;
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE,dragging);
			this.stage.addEventListener(MouseEvent.MOUSE_UP,endDragging);
			e.updateAfterEvent();
		}
		
		private function dragging(e:MouseEvent):void{
			var sy:Number = e.stageY;
			var diff:Number = sy-oldY;
			this.scrollBar.y += diff;
			this.expectedScrollBarY = this.scrollBar.y;
			oldY = sy; 
			dragDiff = diff;
			updatePositions();
			e.updateAfterEvent();
		}
		
		private function endDragging(e:MouseEvent):void{
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE,dragging);
			this.stage.removeEventListener(MouseEvent.MOUSE_UP,endDragging);
			var diff:Number = 0;
			//			if(dragDiff>0) diff = 6;
			//			if(dragDiff<0) diff = -6;
			e.updateAfterEvent();
		}
		
		public function moveDown(dy:Number= 0xffffff):void{
			this.expectedScrollBarY = this.scrollBar.y+dy;
			if(this.auto)
			{
				this.scrollBar.y += dy;
			}
			updatePositions();
		}
		
		public function moveUp(dy:Number = 0xffffff):void{
			this.expectedScrollBarY = this.scrollBar.y-dy;
			if(this.auto)
			{
				this.scrollBar.y -= dy;
			}
			updatePositions();			
		}
		
		public function get displaySize():Rectangle{
			return this.contentScrollPanel.getBounds(this.contentScrollPanel);
		}
		
		public function addItem(value:DisplayObject):DisplayObject{
			return this.contentPanel.addChild(value);
		}
		
		public function removeItem(value:DisplayObject):DisplayObject{
			return this.contentPanel.removeChild(value);
		}
		
		public function removeAll():void{
			GT.removeAllChild(this.contentPanel);
			this.update();
		}
		
		
		override public function get width():Number{return w;}
		override public function get height():Number{return h;}		
		
		override public function set width(newWidth : Number) : void {
			var diff:Number = newWidth - w;
			var oldW:Number,oldH:Number;
			var i:uint,l:uint;			
			this.controlPanel.x +=diff;
			var rect:Rectangle = this.contentScrollPanel.scrollRect;
			rect.width += diff;
			this.contentScrollPanel.scrollRect = rect;
//			GT.fulFill4(this.contentScrollPanel,rect,0,0);
			w = newWidth;
		}
		
		override public function set height(newHeight : Number) : void {
			var diff:Number = newHeight - h;
			var oldW:Number,oldH:Number;
			var i:uint,l:uint;
			var rect:Rectangle = this.contentScrollPanel.scrollRect;
			rect.height += diff;
			this.contentScrollPanel.scrollRect = rect;
//			GT.fulFill4(this.contentScrollPanel,rect,0,0);
			this.downButton.y += diff;
			this.scrollBarBackground.height += diff;
			rect = this.contentPanel.getBounds(this.contentScrollPanel);
			h = newHeight;
			expectedScrollBarY = (this.contentScrollPanel.scrollRect.y*this.scrollBarBackground.height)/rect.height;
			updatePositions();
		}
	}
}